package cn.kgc.cloud.controller;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * @author 课工场
 * @date 2024/1/3
 * @description 引入ribbon负载均衡组件
 * 1.实现服务间调用的负载均衡
 * 2.拉取注册中心服务的地址  ip:port
 */
@RestController
@RequestMapping("exams")
public class ExamController {

    @Resource
    private DiscoveryClient discoveryClient;

    @Resource
    private LoadBalancerClient loadBalancerClient;

    @Resource
    private RestTemplate restTemplate;


    @GetMapping("m1")
    public String method1() {
        //  访问 score  method1    ->  http://localhost:8512/scores
        RestTemplate restTemplate = new RestTemplate();
        String resp = restTemplate.getForObject("http://" + getHost() + "/scores", String.class);
        return "invoke  examService ok  ---invoke scoreService-->  " + resp;
    }

    @GetMapping("m2")
    public String method2() {
        //  访问 score  method1    ->  http://localhost:8512/scores
        RestTemplate restTemplate = new RestTemplate();
        //  从注册中心 获取通信节点信息     服务的名字  获取所有通信节点
        List<ServiceInstance> scoreservices = discoveryClient.getInstances("SCORESERVICE");
        Random random = new Random();
        int index = random.nextInt(scoreservices.size());
        ServiceInstance serviceInstance = scoreservices.get(index);
        //  通过服务节点 获取通信地址
        URI uri = serviceInstance.getUri();
        System.out.println("uri = " + uri);

        // 发送http请求
        String resp = restTemplate.getForObject(uri + "/scores", String.class);

        return "invoke  examService ok  ---invoke scoreService--> " + resp;
    }


    @GetMapping("m3")
    public String method3() {
        //  访问 score  method1
        RestTemplate restTemplate = new RestTemplate();
        //  根据服务名字从注册中心获取服务  默认策略   轮循
        ServiceInstance instance = loadBalancerClient.choose("SCORESERVICE");
        URI uri = instance.getUri();
        // 发送http请求
        String resp = restTemplate.getForObject(uri + "/scores", String.class);
        return "invoke  examService ok  ---invoke scoreService--> " + resp;
    }



    /*
    *   1. 通过ribbon+restTemplate可以实现服务间的通信  但是仍存在不足
    *       1. 请求路径冗余     http://SCORESERVICE/scores/m1   http://SCORESERVICE/scores/m2
    *       2. 路径耦合   不便于维护
    *   解决：
    *      openfeign  通信组件
    * */
    @GetMapping("m4")
    public String method4() {

        String resp = restTemplate.getForObject("http://SCORESERVICE/scores", String.class);
        return "invoke  examService ok  ---invoke scoreService--> " + resp;
    }


    /*
      缺点:
    *  1. 策略单一  获取主机只能随机
       2. 扩展性较差    不能跟随集群中主机的数量改变而改变  固定值
       3. 健康状态无法得到保证
    * */
    public String getHost() {

        List<String> hosts = Arrays.asList("localhost:8512", "localhost:8513", "localhost:8514");
        Random random = new Random();
        int index = random.nextInt(hosts.size());

        return hosts.get(index);
    }

}
